--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Node / ReticulumProjects / MeshChatX.git / files / meshchatx / src / backend / nomadnet_downloader.py
Displaying Raw • Download
meshchatx/src/backend/nomadnet_downloader.py ca36d082fdf638f9b4ba25b7e0eddc94cd66f6db (ca36d082) Text, 9.61 KB
Tff7b72import T7ee787asyncio
Tff7b72import T7ee787io
Tff7b72import T7ee787os
Tff7b72import T7ee787time
Tff7b72from T7ee787collectionsT7ee787.T7ee787abc Tff7b72import Te6edf3Callable
Tff7b72import T7ee787RNS
T8b949e# global cache for nomadnet links to avoid re-establishing them for every request
Te6edf3nomadnet_cached_links Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72class T56d364NomadnetDownloaderTb4b4b4:
Tff7b72def Tff7b72__init__Tb4b4b4(
Tff7b72selfTb4b4b4,
Te6edf3destination_hashTb4b4b4: Tffa657bytesTb4b4b4,
Te6edf3pathTb4b4b4: Tffa657strTb4b4b4,
Te6edf3dataTb4b4b4: Tffa657str Tff7b72| Tff7b72NoneTb4b4b4,
Te6edf3on_download_successTb4b4b4: Te6edf3CallableTb4b4b4[Tb4b4b4[Te6edf3RNSTff7b72.Td2a8ffRequestReceiptTb4b4b4]Tb4b4b4, Tff7b72NoneTb4b4b4]Tb4b4b4,
Te6edf3on_download_failureTb4b4b4: Te6edf3CallableTb4b4b4[Tb4b4b4[Tffa657strTb4b4b4]Tb4b4b4, Tff7b72NoneTb4b4b4]Tb4b4b4,
Te6edf3on_progress_updateTb4b4b4: Te6edf3CallableTb4b4b4[Tb4b4b4[Tffa657floatTb4b4b4]Tb4b4b4, Tff7b72NoneTb4b4b4]Tb4b4b4,
Te6edf3timeoutTb4b4b4: Tffa657int Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffapp_name Tff7b72= Ta5d6ff"Ta5d6ffnomadnetworkTa5d6ff"
Tff7b72selfTff7b72.Td2a8ffaspects Tff7b72= Ta5d6ff"Ta5d6ffnodeTa5d6ff"
Tff7b72selfTff7b72.Td2a8ffdestination_hash Tff7b72= Te6edf3destination_hash
Tff7b72selfTff7b72.Td2a8ffpath Tff7b72= Te6edf3path
Tff7b72selfTff7b72.Td2a8ffdata Tff7b72= Te6edf3data
Tff7b72selfTff7b72.Td2a8fftimeout Tff7b72= Te6edf3timeout
Tff7b72selfTff7b72.Td2a8ff_download_success_callback Tff7b72= Te6edf3on_download_success
Tff7b72selfTff7b72.Td2a8ff_download_failure_callback Tff7b72= Te6edf3on_download_failure
Tff7b72selfTff7b72.Td2a8ffon_progress_update Tff7b72= Te6edf3on_progress_update
Tff7b72selfTff7b72.Td2a8ffrequest_receipt Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffis_cancelled Tff7b72= Tff7b72False
Tff7b72selfTff7b72.Td2a8fflink Tff7b72= Tff7b72None
T8b949e# cancel the download
Tff7b72def Td2a8ffcancelTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffis_cancelled Tff7b72= Tff7b72True
T8b949e# cancel the request if it exists
Tff7b72if Tff7b72selfTff7b72.Td2a8ffrequest_receipt Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffrequest_receiptTff7b72.Td2a8ffcancelTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed to cancel request: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)
T8b949e# clean up the link if we created it
Tff7b72if Tff7b72selfTff7b72.Td2a8fflink Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8fflinkTff7b72.Td2a8ffteardownTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed to teardown link: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)
T8b949e# notify that download was cancelled
Tff7b72selfTff7b72.Td2a8ff_download_failure_callbackTb4b4b4(Ta5d6ff"Ta5d6ffcancelledTa5d6ff"Tb4b4b4)
T8b949e# setup link to destination and request download
Tff7b72async Tff7b72def Td2a8ffdownloadTb4b4b4(
Tff7b72selfTb4b4b4,
Te6edf3path_lookup_timeoutTb4b4b4: Tffa657int Tff7b72= T79c0ff15Tb4b4b4,
Te6edf3link_establishment_timeoutTb4b4b4: Tffa657int Tff7b72= T79c0ff15Tb4b4b4,
Tb4b4b4)Tb4b4b4:
T8b949e# check if cancelled before starting
Tff7b72if Tff7b72selfTff7b72.Td2a8ffis_cancelledTb4b4b4:
Tff7b72return
T8b949e# use existing established link if it's active
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdestination_hash Tff7b72in Te6edf3nomadnet_cached_linksTb4b4b4:
Te6edf3link Tff7b72= Te6edf3nomadnet_cached_linksTb4b4b4[Tff7b72selfTff7b72.Td2a8ffdestination_hashTb4b4b4]
Tff7b72if Te6edf3linkTff7b72.Td2a8ffstatus Tff7b72is Te6edf3RNSTff7b72.Td2a8ffLinkTff7b72.Td2a8ffACTIVETb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ff[NomadnetDownloader] using existing link for requestTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8fflink_establishedTb4b4b4(Te6edf3linkTb4b4b4)
Tff7b72return
T8b949e# determine when to timeout
Te6edf3timeout_after_seconds Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72+ Te6edf3path_lookup_timeout
T8b949e# check if we have a path to the destination
Tff7b72if Tff7b72not Te6edf3RNSTff7b72.Td2a8ffTransportTff7b72.Td2a8ffhas_pathTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdestination_hashTb4b4b4)Tb4b4b4:
T8b949e# we don't have a path, so we need to request it
Te6edf3RNSTff7b72.Td2a8ffTransportTff7b72.Td2a8ffrequest_pathTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdestination_hashTb4b4b4)
T8b949e# wait until we have a path, or give up after the configured timeout
Tff7b72while Tb4b4b4(
Tff7b72not Te6edf3RNSTff7b72.Td2a8ffTransportTff7b72.Td2a8ffhas_pathTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdestination_hashTb4b4b4)
Tff7b72and Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72< Te6edf3timeout_after_seconds
Tb4b4b4)Tb4b4b4:
T8b949e# check if cancelled during path lookup
Tff7b72if Tff7b72selfTff7b72.Td2a8ffis_cancelledTb4b4b4:
Tff7b72return
Tff7b72await Te6edf3asyncioTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.1Tb4b4b4)
T8b949e# if we still don't have a path, we can't establish a link, so bail out
Tff7b72if Tff7b72not Te6edf3RNSTff7b72.Td2a8ffTransportTff7b72.Td2a8ffhas_pathTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdestination_hashTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_download_failure_callbackTb4b4b4(Ta5d6ff"Ta5d6ffCould not find path to destination.Ta5d6ff"Tb4b4b4)
Tff7b72return
T8b949e# check if cancelled before establishing link
Tff7b72if Tff7b72selfTff7b72.Td2a8ffis_cancelledTb4b4b4:
Tff7b72return
T8b949e# create destination to nomadnet node
Te6edf3identity Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffrecallTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdestination_hashTb4b4b4)
Te6edf3destination Tff7b72= Te6edf3RNSTff7b72.Td2a8ffDestinationTb4b4b4(
Te6edf3identityTb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffDestinationTff7b72.Td2a8ffOUTTb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffDestinationTff7b72.Td2a8ffSINGLETb4b4b4,
Tff7b72selfTff7b72.Td2a8ffapp_nameTb4b4b4,
Tff7b72selfTff7b72.Td2a8ffaspectsTb4b4b4,
Tb4b4b4)
T8b949e# create link to destination
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ff[NomadnetDownloader] establishing new link for requestTa5d6ff"Tb4b4b4)
Te6edf3link Tff7b72= Te6edf3RNSTff7b72.Td2a8ffLinkTb4b4b4(Te6edf3destinationTb4b4b4, Te6edf3established_callbackTff7b72=Tff7b72selfTff7b72.Td2a8fflink_establishedTb4b4b4)
Tff7b72selfTff7b72.Td2a8fflink Tff7b72= Te6edf3link
T8b949e# determine when to timeout
Te6edf3timeout_after_seconds Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72+ Te6edf3link_establishment_timeout
T8b949e# wait until we have established a link, or give up after the configured timeout
Tff7b72while Tb4b4b4(
Te6edf3linkTff7b72.Td2a8ffstatus Tff7b72is Tff7b72not Te6edf3RNSTff7b72.Td2a8ffLinkTff7b72.Td2a8ffACTIVE Tff7b72and Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72< Te6edf3timeout_after_seconds
Tb4b4b4)Tb4b4b4:
T8b949e# check if cancelled during link establishment
Tff7b72if Tff7b72selfTff7b72.Td2a8ffis_cancelledTb4b4b4:
Tff7b72return
Tff7b72await Te6edf3asyncioTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.1Tb4b4b4)
T8b949e# if we still haven't established a link, bail out
Tff7b72if Te6edf3linkTff7b72.Td2a8ffstatus Tff7b72is Tff7b72not Te6edf3RNSTff7b72.Td2a8ffLinkTff7b72.Td2a8ffACTIVETb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_download_failure_callbackTb4b4b4(Ta5d6ff"Ta5d6ffCould not establish link to destination.Ta5d6ff"Tb4b4b4)
T8b949e# link to destination was established, we should now request the download
Tff7b72def Td2a8fflink_establishedTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3linkTb4b4b4)Tb4b4b4:
T8b949e# check if cancelled before requesting
Tff7b72if Tff7b72selfTff7b72.Td2a8ffis_cancelledTb4b4b4:
Tff7b72return
T8b949e# cache link for using in future requests
Te6edf3nomadnet_cached_linksTb4b4b4[Tff7b72selfTff7b72.Td2a8ffdestination_hashTb4b4b4] Tff7b72= Te6edf3link
T8b949e# request download over link
Tff7b72selfTff7b72.Td2a8ffrequest_receipt Tff7b72= Te6edf3linkTff7b72.Td2a8ffrequestTb4b4b4(
Tff7b72selfTff7b72.Td2a8ffpathTb4b4b4,
Te6edf3dataTff7b72=Tff7b72selfTff7b72.Td2a8ffdataTb4b4b4,
Te6edf3response_callbackTff7b72=Tff7b72selfTff7b72.Td2a8ffon_responseTb4b4b4,
Te6edf3failed_callbackTff7b72=Tff7b72selfTff7b72.Td2a8ffon_failedTb4b4b4,
Te6edf3progress_callbackTff7b72=Tff7b72selfTff7b72.Td2a8ffon_progressTb4b4b4,
Te6edf3timeoutTff7b72=Tff7b72selfTff7b72.Td2a8fftimeoutTb4b4b4,
Tb4b4b4)
T8b949e# handle successful download
Tff7b72def Td2a8ffon_responseTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3request_receiptTb4b4b4: Te6edf3RNSTff7b72.Td2a8ffRequestReceiptTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_download_success_callbackTb4b4b4(Te6edf3request_receiptTb4b4b4)
T8b949e# handle failure
Tff7b72def Td2a8ffon_failedTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3request_receiptTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_download_failure_callbackTb4b4b4(Ta5d6ff"Ta5d6ffrequest_failedTa5d6ff"Tb4b4b4)
T8b949e# handle download progress
Tff7b72def Td2a8ffon_progressTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3request_receiptTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffon_progress_updateTb4b4b4(Te6edf3request_receiptTff7b72.Td2a8ffprogressTb4b4b4)
Tff7b72class T56d364NomadnetPageDownloaderTb4b4b4(Te6edf3NomadnetDownloaderTb4b4b4)Tb4b4b4:
Tff7b72def Tff7b72__init__Tb4b4b4(
Tff7b72selfTb4b4b4,
Te6edf3destination_hashTb4b4b4: Tffa657bytesTb4b4b4,
Te6edf3page_pathTb4b4b4: Tffa657strTb4b4b4,
Te6edf3dataTb4b4b4: Tffa657str Tff7b72| Tff7b72NoneTb4b4b4,
Te6edf3on_page_download_successTb4b4b4: Te6edf3CallableTb4b4b4[Tb4b4b4[Tffa657strTb4b4b4]Tb4b4b4, Tff7b72NoneTb4b4b4]Tb4b4b4,
Te6edf3on_page_download_failureTb4b4b4: Te6edf3CallableTb4b4b4[Tb4b4b4[Tffa657strTb4b4b4]Tb4b4b4, Tff7b72NoneTb4b4b4]Tb4b4b4,
Te6edf3on_progress_updateTb4b4b4: Te6edf3CallableTb4b4b4[Tb4b4b4[Tffa657floatTb4b4b4]Tb4b4b4, Tff7b72NoneTb4b4b4]Tb4b4b4,
Te6edf3timeoutTb4b4b4: Tffa657int Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffon_page_download_success Tff7b72= Te6edf3on_page_download_success
Tff7b72selfTff7b72.Td2a8ffon_page_download_failure Tff7b72= Te6edf3on_page_download_failure
Tffa657superTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ff__init__Tb4b4b4(
Te6edf3destination_hashTb4b4b4,
Te6edf3page_pathTb4b4b4,
Te6edf3dataTb4b4b4,
Tff7b72selfTff7b72.Td2a8ffon_download_successTb4b4b4,
Tff7b72selfTff7b72.Td2a8ffon_download_failureTb4b4b4,
Te6edf3on_progress_updateTb4b4b4,
Te6edf3timeoutTb4b4b4,
Tb4b4b4)
T8b949e# page download was successful, decode the response and send to provided callback
Tff7b72def Td2a8ffon_download_successTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3request_receiptTb4b4b4: Te6edf3RNSTff7b72.Td2a8ffRequestReceiptTb4b4b4)Tb4b4b4:
Te6edf3micron_markup_response Tff7b72= Te6edf3request_receiptTff7b72.Td2a8ffresponseTff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffon_page_download_successTb4b4b4(Te6edf3micron_markup_responseTb4b4b4)
T8b949e# page download failed, send error to provided callback
Tff7b72def Td2a8ffon_download_failureTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3failure_reasonTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffon_page_download_failureTb4b4b4(Te6edf3failure_reasonTb4b4b4)
Tff7b72class T56d364NomadnetFileDownloaderTb4b4b4(Te6edf3NomadnetDownloaderTb4b4b4)Tb4b4b4:
Tff7b72def Tff7b72__init__Tb4b4b4(
Tff7b72selfTb4b4b4,
Te6edf3destination_hashTb4b4b4: Tffa657bytesTb4b4b4,
Te6edf3page_pathTb4b4b4: Tffa657strTb4b4b4,
Te6edf3on_file_download_successTb4b4b4: Te6edf3CallableTb4b4b4[Tb4b4b4[Tffa657strTb4b4b4, Tffa657bytesTb4b4b4]Tb4b4b4, Tff7b72NoneTb4b4b4]Tb4b4b4,
Te6edf3on_file_download_failureTb4b4b4: Te6edf3CallableTb4b4b4[Tb4b4b4[Tffa657strTb4b4b4]Tb4b4b4, Tff7b72NoneTb4b4b4]Tb4b4b4,
Te6edf3on_progress_updateTb4b4b4: Te6edf3CallableTb4b4b4[Tb4b4b4[Tffa657floatTb4b4b4]Tb4b4b4, Tff7b72NoneTb4b4b4]Tb4b4b4,
Te6edf3timeoutTb4b4b4: Tffa657int Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffon_file_download_success Tff7b72= Te6edf3on_file_download_success
Tff7b72selfTff7b72.Td2a8ffon_file_download_failure Tff7b72= Te6edf3on_file_download_failure
Tffa657superTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ff__init__Tb4b4b4(
Te6edf3destination_hashTb4b4b4,
Te6edf3page_pathTb4b4b4,
Tff7b72NoneTb4b4b4,
Tff7b72selfTff7b72.Td2a8ffon_download_successTb4b4b4,
Tff7b72selfTff7b72.Td2a8ffon_download_failureTb4b4b4,
Te6edf3on_progress_updateTb4b4b4,
Te6edf3timeoutTb4b4b4,
Tb4b4b4)
T8b949e# file download was successful, decode the response and send to provided callback
Tff7b72def Td2a8ffon_download_successTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3request_receiptTb4b4b4: Te6edf3RNSTff7b72.Td2a8ffRequestReceiptTb4b4b4)Tb4b4b4:
T8b949e# get response
Te6edf3response Tff7b72= Te6edf3request_receiptTff7b72.Td2a8ffresponse
T8b949e# handle buffered reader response
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3responseTb4b4b4, Te6edf3ioTff7b72.Td2a8ffBufferedReaderTb4b4b4)Tb4b4b4:
T8b949e# get file name from metadata
Te6edf3file_name Tff7b72= Ta5d6ff"Ta5d6ffdownloaded_fileTa5d6ff"
Te6edf3metadata Tff7b72= Te6edf3request_receiptTff7b72.Td2a8ffmetadata
Tff7b72if Te6edf3metadata Tff7b72is Tff7b72not Tff7b72None Tff7b72and Ta5d6ff"Ta5d6ffnameTa5d6ff" Tff7b72in Te6edf3metadataTb4b4b4:
Te6edf3file_path Tff7b72= Te6edf3metadataTb4b4b4[Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4]Tff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)
Te6edf3file_name Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Te6edf3file_pathTb4b4b4)
T8b949e# get file data
Te6edf3file_dataTb4b4b4: Tffa657bytes Tff7b72= Te6edf3responseTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffon_file_download_successTb4b4b4(Te6edf3file_nameTb4b4b4, Te6edf3file_dataTb4b4b4)
Tff7b72return
T8b949e# check for list response with bytes in position 0, and metadata dict in position 1
T8b949e# e.g: [file_bytes, {name: "filename.ext"}]
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3responseTb4b4b4, Tffa657listTb4b4b4) Tff7b72and Tffa657isinstanceTb4b4b4(Te6edf3responseTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Te6edf3file_dataTb4b4b4: Tffa657bytes Tff7b72= Te6edf3responseTb4b4b4[T79c0ff0Tb4b4b4]
Te6edf3metadataTb4b4b4: Tffa657dict Tff7b72= Te6edf3responseTb4b4b4[T79c0ff1Tb4b4b4]
T8b949e# get file name from metadata
Te6edf3file_name Tff7b72= Ta5d6ff"Ta5d6ffdownloaded_fileTa5d6ff"
Tff7b72if Te6edf3metadata Tff7b72is Tff7b72not Tff7b72None Tff7b72and Ta5d6ff"Ta5d6ffnameTa5d6ff" Tff7b72in Te6edf3metadataTb4b4b4:
Te6edf3file_path Tff7b72= Te6edf3metadataTb4b4b4[Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4]Tff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)
Te6edf3file_name Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Te6edf3file_pathTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffon_file_download_successTb4b4b4(Te6edf3file_nameTb4b4b4, Te6edf3file_dataTb4b4b4)
Tff7b72return
T8b949e# try using original response format
T8b949e# unsure if this is actually used anymore now that a buffered reader is provided
T8b949e# have left here just in case...
Tff7b72tryTb4b4b4:
Te6edf3file_nameTb4b4b4: Tffa657str Tff7b72= Te6edf3responseTb4b4b4[T79c0ff0Tb4b4b4]
Te6edf3file_dataTb4b4b4: Tffa657bytes Tff7b72= Te6edf3responseTb4b4b4[T79c0ff1Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ffon_file_download_successTb4b4b4(Te6edf3file_nameTb4b4b4, Te6edf3file_dataTb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffon_download_failureTb4b4b4(Ta5d6ff"Ta5d6ffunsupported_responseTa5d6ff"Tb4b4b4)
T8b949e# page download failed, send error to provided callback
Tff7b72def Td2a8ffon_download_failureTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3failure_reasonTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffon_file_download_failureTb4b4b4(Te6edf3failure_reasonTb4b4b4)
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────